package com.rainbow.support.xss.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.rainbow.support.xss.handler.JsonDeserializer;
import com.rainbow.support.xss.handler.JsonXssCleaner;
import com.rainbow.support.xss.handler.JsonXssSerializer;
import com.rainbow.support.xss.handler.XssHandlerFilter;
import com.rainbow.support.xss.properties.XssProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

/**
 * @author rainbow
 */
@Configuration
@EnableConfigurationProperties(XssProperties.class)
@ConditionalOnProperty(prefix = XssProperties.XSS_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
public class XssAutoConfig {


	/**
	 * Xss 清理者
	 * @return XssCleaner
	 */
	@ConditionalOnMissingBean(JsonXssCleaner.class)
	@Primary
	@Bean(name="xssCleaner")
	public JsonXssCleaner xssCleaner(XssProperties xssProperties) {
		return new JsonXssCleaner(xssProperties);
	}



	/**
	 * 主要用于过滤 QueryString, Header 以及 form 中的参数
	 * @param xssProperties 安全配置类
	 * @return FilterRegistrationBean
	 */
	@Bean
	@Order(Ordered.HIGHEST_PRECEDENCE)
	public FilterRegistrationBean<XssHandlerFilter> xssFilterRegistrationBean(XssProperties xssProperties) {
		FilterRegistrationBean<XssHandlerFilter> registration = new FilterRegistrationBean<>();
		registration.setFilter(new XssHandlerFilter(xssProperties));
		registration.setName("xssFilter");
		registration.setOrder(-1);
		return registration;
	}

	/**
	 * 注册 Jackson 的序列化器，
	 * 用于处理 json 类型参数的 xss 过滤
	 * @return Jackson2ObjectMapperBuilderCustomizer
	 */
	@Bean
	@Primary
	public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(JsonXssCleaner xssCleaner) {
		// 在反序列化时进行 xss 过滤，可以替换使用 XssStringJsonSerializer，在序列化时进行处理
		return builder -> builder.deserializerByType(String.class, new JsonDeserializer(xssCleaner));
	}


	/**
	 * 返回结果过滤json类型
	 * @param builder 解析器
	 * @return json处理器
	 */
	@Bean
	@Primary
	public ObjectMapper xssObjectMapper(Jackson2ObjectMapperBuilder builder,JsonXssCleaner jsonXssCleaner) {
		//解析器
		ObjectMapper objectMapper = builder.createXmlMapper(false).build();
		//注册xss解析器
		SimpleModule xssModule = new SimpleModule("jsonXssSerializer");
		xssModule.addSerializer(new JsonXssSerializer(jsonXssCleaner));
		objectMapper.registerModule(xssModule);
		return objectMapper;
	}


}
